package com.whately.core.base.utils;

public class RadixNumberUtils {

    /**
     * 支持的最小进制
     */
    public static int MIN_RADIX = 2;
    /**
     * 支持的最大进制
     */
    public static int MAX_RADIX = 62;

    /**
     * 锁定创建
     */
    private RadixNumberUtils() {
    }

    /**
     * 字典顺序
     * 0-9A-Za-z表示62进制内的 0到61。
     */
    private static final String num62Ordered = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";

    /**
     * 字典顺序
     * A-Za-z
     */
    private static final String NUM_52_ORDERED = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";


    //private static final String[] confused_num62_array = {"XEFGHIJ0123456789ABCDKLMNjklmnopqOPQRSTUVWYZabcdefghirstuvwxyz","Y56789AFGHIJKLM01234NOPQRSTUVWXZabcdefghijklmBCDEnopqrstuvwxyz","Zcdefghij0123456789ABCLMNOPQRSTUVWXYabklmnopqrstuvwxyzDEFGHIJK"};

    /**
     * 把10进制数字转字母
     */
    public static String convertToChars(long number) {
        return dec2Any(number,NUM_52_ORDERED.length(),NUM_52_ORDERED);
    }

    public static long reconvertCharsToNumber(String numberOtherHex) {
        return any2Dec(numberOtherHex,NUM_52_ORDERED.length(),NUM_52_ORDERED);
    }

    public static String convertTo62(long number) {
        return dec2Any(number,num62Ordered.length(),num62Ordered);
    }

    public static long reconvert62ToNumber(String numberOtherHex) {
        return any2Dec(numberOtherHex,num62Ordered.length(),num62Ordered);
    }

    /*
    public static String convertTo36(long number) {
        return dec2Any(number,36,num62Ordered);
    }

    public static long reconvert36ToNumber(String numberOtherHex) {
        return any2Dec(numberOtherHex,36,num62Ordered);
    }

    public static String mixConvertTo62(long number) {
        int random = IntegerUtils.random(0, confused_num62_array.length-1);
        return confused_num62_array[random].charAt(0)+dec2Any(number,62,confused_num62_array[random]);
    }

    public static long mixReconvert62ToNumber(String numberOtherHex) {
        char first = numberOtherHex.charAt(0);
        int random;
        switch (first){
            case 'X':random = 0;break;
            case 'Y':random = 1;break;
            case 'Z':random = 2;break;
            default:throw new ServiceException(400,"error change dyReconvert62ToNumber :"+numberOtherHex);
        }

        return any2Dec(numberOtherHex,62,confused_num62_array[random]);
    }
     */

    /**
     * 返回一字符串，包含 number 以 toRadix 进制的表示。<br />
     * number 本身的进制由 fromRadix 指定。fromRadix 和 toRadix 都只能在 2 和 62 之间（包括 2 和 62）。<br />
     * 高于十进制的数字用字母 a-zA-Z 表示，例如 a 表示 10，b 表示 11 以及 Z 表示 62。<br />
     *
     * @param number    需要转换的数字
     * @param fromRadix 输入进制
     * @param toRadix   输出进制
     * @return 指定输出进制的数字
     */
    /*private static String baseConvert(String number, int fromRadix, int toRadix,String num62) {
        long dec = any2Dec(number, fromRadix,num62);
        return dec2Any(dec, toRadix,num62);
    }*/

    /**
     * 返回一字符串，包含 十进制 number 以 radix 进制的表示。
     *
     * @param dec     需要转换的数字
     * @param toRadix 输出进制。当不在转换范围内时，此参数会被设定为 2，以便及时发现。
     * @return 指定输出进制的数字
     */
    private static String dec2Any(long dec, int toRadix,String num62) {
        if (toRadix < MIN_RADIX || toRadix > MAX_RADIX) {
            toRadix = 2;
        }
        if (toRadix == 10) {
            return String.valueOf(dec);
        }
        // -Long.MIN_VALUE 转换为 2 进制时长度为65
        char[] buf = new char[65]; //
        int charPos = 64;
        boolean isNegative = (dec < 0);
        if (!isNegative) {
            dec = -dec;
        }
        while (dec <= -toRadix) {
            buf[charPos--] = num62.charAt((int) (-(dec % toRadix)));
            dec = dec / toRadix;
        }
        buf[charPos] = num62.charAt((int) (-dec));
        if (isNegative) {
            buf[--charPos] = '-';
        }
        return new String(buf, charPos, (65 - charPos));
    }

    /**
     * 返回一字符串，包含 number 以 10 进制的表示。<br />
     * fromBase 只能在 2 和 62 之间（包括 2 和 62）。
     *
     * @param number    输入数字
     * @param fromRadix 输入进制
     * @return 十进制数字
     */
    private static long any2Dec(String number, int fromRadix,String num62) {
        long dec = 0;
        long digitValue = 0;
        int len = number.length() - 1;
        for (int t = 0; t <= len; t++) {
            digitValue = num62.indexOf(number.charAt(t));
            dec = dec * fromRadix + digitValue;
        }
        return dec;

    }
}
